import React from 'react';
import axios from "axios";
import config from "../api.json";
import CommonUtils from "./CommonUtils";
import EventsUtils from "./EventsUtils";
import Index from "../components/loading";
import AlertUtils from "./AlertUtils";
import DialogBuilder from "./DialogBuilder";
import LoginPage from "../pages/login";

//请求前处理
axios.interceptors.request.use(request=>{
    RequestUtils.requestCount++;
    return request;
}, error => {
    RequestUtils.requestCount--;
    AlertUtils.danger("发送请求失败，请联系管理员，或给我们反馈!", 5000);
});
//响应结果处理
axios.interceptors.response.use(response=>{
    RequestUtils.requestCount--;
    return response;
}, error => {
    RequestUtils.requestCount--;
    let tip;
    if(typeof error.response !== 'object'){
        tip = "网络链接错误，请检查您的网络设置!";
    }
    else {
        let defaultTip = error.response.data && (error.response.data.tip || error.response.data.message);
        switch (error.response.status) {
            case 401:
                let dialog = new DialogBuilder(<LoginPage success={()=>dialog.remove()}/>).show();
                tip = defaultTip || "请重新登录";
                break;
            case 403:
                if(typeof error.response.config.headers["X-XSRF-TOKEN"] !== 'string'){
                    return axios.request(error.config);
                }
                tip = defaultTip || "您没有该操作权限";
                break;
            case 404:
                tip = defaultTip || "您访问的资源不存在";
                break;
            case 500:
                tip = defaultTip || "服务器内部错误，请联系管理员，或给我们反馈";
                break;
            default:
                tip = defaultTip || error.response.statusText;
                break;
        }
    }
    AlertUtils.danger(tip, 5000);
    return Promise.reject(error);
});
axios.defaults.withCredentials = true;
axios.defaults.paramsSerializer = function (params) {
    function formatterParam(name, value) {
        name = encodeURI(name);
        switch (typeof value) {
            case "string":
                return name + "=" + encodeURI(value);
            case "number":
                return name + "=" + value;
            case "object":
                if(value[Symbol.iterator])
                    return value.map(item=>name+"="+encodeURI(item)).join("&");
                return name + "=" + encodeURI(JSON.stringify(value));
            case "undefined":
                return name + "=" + value;
            case "boolean":
                return name + "=" + value;
            default:
                break;
        }
    }
    if(typeof params === "string"){
        return params;
    }else if(params instanceof Array){
        return params.map(param=>formatterParam(param.name, param.value)).join("&");
    }else if(params instanceof Map){
        return params.map((name, value)=>formatterParam(name, value)).join("&");
    }else if(params instanceof Object){
        return Object.keys(params).map(name=>formatterParam(name, params[name])).join("&");
    }else throw new TypeError("未知的数据类型");
};

/**
 * Http请求工具，会处理和显示错误，简化ajax请求编码
 */
export default class RequestUtils {
    static ajax(url, options){
        if(typeof url === 'object'){
            options = url;
            url = undefined;
        }
        options.url = url || options.url;
        if(!options.url.startsWith("http"))
            options.url = config.host + options.url;
        return axios.request(options);
    }

    static api(options){
        options.url = config.host + options.url;
        return axios.request(options);
    }

    /**
     * 获取请求总数
     * @return {Number}
     */
    static get requestCount(){
        if(RequestUtils._requestCount === undefined){
            return 0;
        }
        return RequestUtils._requestCount;
    }

    /**
     * 设置请求总数
     * @param val {Number}
     */
    static set requestCount(val){
        if(val > 0){
            EventsUtils.emit(Index.events.LOADING);
        }else {
            EventsUtils.emit(Index.events.COMPLETE);
        }
        RequestUtils._requestCount = val;
    }
}

for (let key in config.apis) {
    RequestUtils[key] = option=>RequestUtils.api(
        CommonUtils.extend(CommonUtils.clone(config.apis[key]), option)
    );
}
